const { defineConfig } = require("@vue/cli-service")
const path = require("path")
const CompressionPlugin = require("compression-webpack-plugin") // 压缩插件，用于生成.br/.gz等压缩文件(v6+才支持Brotli算法)
const TerserPlugin = require("terser-webpack-plugin") // 压缩插件，用于压缩js文件

module.exports = defineConfig({
    transpileDependencies: true, // 忽略node_modules

    // 以下是我自定义的配置
    // 基础配置
    publicPath: "./", // 部署应用包时的基本 URL
    outputDir: "dist_", // 构建输出目录
    assetsDir: "static", // 放置静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录
    lintOnSave: false, // 是否在开发环境下通过 eslint-loader 在每次保存时 lint 代码

    // 开发环境配置
    devServer: {
        port: 6000, // 固定端口号
        // hot: true, // 开启热更新（默认是开启的）
        compress: true, // 开发环境启用压缩
    },

    chainWebpack: (config) => {
        // 减少组件重复打包，比如对引用3次以上的组件进行抽离
        config.optimization.splitChunks({
            cacheGroups: {
                common: {
                    name: "chunk-common",
                    chunks: "initial",
                    minChunks: 2, // 最小引用次数
                    maxInitialRequests: 5, // 最大初始加载次数
                    minSize: 0,
                    priority: 1,
                    reuseExistingChunk: true,
                },
                vendor: {
                    name: "chunk-vendors",
                    test: /[\\/]node_modules[\\/]/,
                    chunks: "initial",
                    priority: 2,
                    reuseExistingChunk: true,
                    enforce: true,
                },
            },
        }),
            // 图片转base64规则
            config.module.rule("images").set("parser", {
                dataUrlCondition: {
                    maxSize: 50 * 1024, // 50KB阈值
                },
            })

        // 生产环境优化
        if (process.env.NODE_ENV === "production") {
            config.optimization.minimize(true) // 开启压缩
        }

        // 自动加载所有svg文件（为封装的SVG组件用）
        config.module.rule("svg").exclude.add(path.resolve(__dirname, "src/assets/svg")).end()
        config.module
            .rule("icons")
            .test(/\.svg$/)
            .include.add(path.resolve(__dirname, "src/assets/svg"))
            .end()
            .use("svg-sprite-loader")
            .loader("svg-sprite-loader")
            .options({ symbolId: "icon-[name]" })
    },

    css: {
        loaderOptions: {
            sass: {
                // additionalData: `~@import "@/assets/styles/public.scss";`, // 全局使用的样式(不同sass-loader版本写法不同)
            },
        },
    },

    // 生产环境配置
    productionSourceMap: false, // 关闭sourcemap
    filenameHashing: true, // 开启文件哈希

    // Webpack 核心配置
    configureWebpack: {
        // 别名配置
        resolve: {
            alias: {
                "@public": path.resolve(__dirname, "public"), // 静态资源别名
                "@": path.resolve(__dirname, "src"), // src别名
            },
        },
        // 优化配置
        optimization: {
            splitChunks: {
                chunks: "all",
                minSize: 50000, // 大于50KB将会被分包（通常设置200左右）
                // maxSize: 500000, // 500KB分包阈值
                cacheGroups: {
                    vendors: {
                        test: /[\\/]node_modules[\\/]/, // 匹配node_modules目录下的文件
                        priority: -10, // 优先级
                        reuseExistingChunk: true, // 重用已存在的chunk
                    },
                },
            },
            // 压缩配置
            minimizer: [
                new TerserPlugin({
                    terserOptions: {
                        compress: {
                            drop_console: true, // 移除console
                        },
                    },
                }),
            ],
        },
        plugins: [
            // gzip压缩
            new CompressionPlugin({
                filename: "[path][base].gz",
                algorithm: "gzip",
                test: /\.(js|css|html|svg)$/,
                threshold: 10240,
                minRatio: 0.8,
            }),
            // br压缩
            new CompressionPlugin({
                filename: "[path][base].br",
                algorithm: "brotliCompress", // 强制指定使用Brotli算法
                test: /\.(js|css|html|svg)$/, // 只压缩这些类型的静态资源
                threshold: 1024, // 只有大小大于1KB的静态资源才会被压缩
                minRatio: 0.8, // 只有压缩率比这个值小的资源才会被压缩
                compressionOptions: { level: 11 }, // Brotli压缩级别，最高为11
            }),
            {
                apply: (compiler) => {
                    compiler.hooks.beforeRun.tap("BeforeBuild", () => {
                        console.log("打包开始")
                        // 可以在此处执行一些操作，比如图片压缩、改名测试的.vue文件等
                    })

                    compiler.hooks.done.tap("AfterBuild", () => {
                        console.log("打包完成")
                    })
                },
            },
        ],
    },
})
